/*******************************************************************************
 * Copyright (c) 2006 CEA List.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     CEA List - initial API and implementation
 *******************************************************************************/
package com.cea.papyrus.diagram.statemachine;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.gef.palette.MarqueeToolEntry;
import org.eclipse.gef.palette.PaletteContainer;
import org.eclipse.gef.palette.PaletteDrawer;
import org.eclipse.gef.palette.PaletteGroup;
import org.eclipse.gef.palette.PaletteRoot;
import org.eclipse.gef.palette.PaletteSeparator;
import org.eclipse.gef.palette.PaletteStack;
import org.eclipse.gef.palette.PanningSelectionToolEntry;
import org.eclipse.gef.palette.ToolEntry;
import org.eclipse.gef.ui.palette.FlyoutPaletteComposite.FlyoutPreferences;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.uml2.uml.Comment;
import org.eclipse.uml2.uml.ConnectionPointReference;
import org.eclipse.uml2.uml.Constraint;
import org.eclipse.uml2.uml.FinalState;
import org.eclipse.uml2.uml.Region;
import org.eclipse.uml2.uml.State;
import org.eclipse.uml2.uml.StateMachine;
import org.eclipse.uml2.uml.Transition;

import com.cea.papyrus.core.IPapyrusUIConstants;
import com.cea.papyrus.core.PapyrusMessages;
import com.cea.papyrus.core.PapyrusPlugin;
import com.cea.papyrus.core.editor.CreationEntryFactory;
import com.cea.papyrus.core.editor.DiagramPalette;
import com.cea.papyrus.core.pseudoelement.GraphicalLink;
import com.cea.papyrus.core.ui.dialogs.PapyrusMessageDialog;
import com.cea.papyrus.core.utils.Debug;
import com.cea.papyrus.diagram.statemachine.pseudoelement.Choice;
import com.cea.papyrus.diagram.statemachine.pseudoelement.DeepHistory;
import com.cea.papyrus.diagram.statemachine.pseudoelement.EntryPoint;
import com.cea.papyrus.diagram.statemachine.pseudoelement.ExitPoint;
import com.cea.papyrus.diagram.statemachine.pseudoelement.Fork;
import com.cea.papyrus.diagram.statemachine.pseudoelement.Initial;
import com.cea.papyrus.diagram.statemachine.pseudoelement.Join;
import com.cea.papyrus.diagram.statemachine.pseudoelement.Junction;
import com.cea.papyrus.diagram.statemachine.pseudoelement.ShallowHistory;
import com.cea.papyrus.diagram.statemachine.pseudoelement.Terminate;

/**
 * The Class StateMachinePaletteFactory. 
 * Manages creation of the palette in the state machine diagram editor.
 * 
 * @author David Servat
 * @since 29 jan. 07
 */
public final class StateMachinePaletteFactory extends CreationEntryFactory{

	/**
	 * The channel.
	 */
	private static int channel = 501;

	/**
	 * Preference ID used to persist the palette location.
	 */
	private static final String PALETTE_DOCK_LOCATION = "ShapesEditorPaletteFactory.Location";
	
	/**
	 * Preference ID used to persist the palette size.
	 */
	private static final String PALETTE_SIZE = "ShapesEditorPaletteFactory.Size";
	
	/**
	 * Preference ID used to persist the flyout palette's state.
	 */
	private static final String PALETTE_STATE = "ShapesEditorPaletteFactory.State";

	/**
	 * Creates the PaletteRoot and adds all palette elements.
	 * Use this factory method to create a new palette for your graphical editor.
	 * 
	 * @return a new PaletteRoot
	 */
	public static DiagramPalette createPalette(){
		Debug.debug(null,"Call ClassDiagramPaletteFactory.createPalette()", channel);
		//Darpan changed this from CLASS_DIAGRAM to STATE_MACHINE_DIAGRAM
		DiagramPalette palette = new DiagramPalette(IPapyrusUIConstants.STATE_MACHINE_DIAGRAM);
		palette.add(createToolsGroup(palette));
		palette.add(createShapesDrawer());

		//create additionnal menu defined in extensions
		palette.createMenuExtensions();

		return palette;
	}

	/**
	 * Return a FlyoutPreferences instance used to save/load the preferences of
	 * a flyout palette.
	 * 
	 * @return the flyout preferences
	 */
	static FlyoutPreferences createPalettePreferences(){
		Debug.debug(null,"Call StateMachinePaletteFactory.createPalettePreferences()", channel);
		return new FlyoutPreferences(){
			private IPreferenceStore getPreferenceStore(){
				return Activator.getDefault().getPreferenceStore();
			}
			public int getDockLocation(){
				return getPreferenceStore().getInt(PALETTE_DOCK_LOCATION);
			}
			public int getPaletteState(){
				return getPreferenceStore().getInt(PALETTE_STATE);
			}
			public int getPaletteWidth(){
				return getPreferenceStore().getInt(PALETTE_SIZE);
			}
			public void setDockLocation(int location){
				getPreferenceStore().setValue(PALETTE_DOCK_LOCATION, location);
			}
			public void setPaletteState(int state){
				getPreferenceStore().setValue(PALETTE_STATE, state);
			}
			public void setPaletteWidth(int width){
				getPreferenceStore().setValue(PALETTE_SIZE, width);
			}
		};
	}

	/**
	 * Create the "Shapes" drawer.
	 * 
	 * @return the palette container
	 */
	private static PaletteContainer createShapesDrawer(){
		Debug.debug(null,"Call StateMachinePaletteFactory.createShapesDrawer()", channel);
		PaletteDrawer componentsDrawer = new PaletteDrawer("Uml Element");

		List entries = new ArrayList();
		try{
			PaletteStack paletteStack = new PaletteStack("", "", null);
			//StateMachine
			paletteStack.add(PapyrusPlugin.creationToolFactory.getCombinedTemplateCreationToolEntry(
					PapyrusMessages.AddStateMachineCommand_Label
					, PapyrusMessages.AddStateMachineCommand_Description
					, StateMachine.class
					, null));
			//ProtocolStateMachine
//			paletteStack.add(PapyrusPlugin.creationToolFactory.getCombinedTemplateCreationToolEntry(
//					PapyrusMessages.AddProtocolStateMachineCommand_Label
//					, PapyrusMessages.AddProtocolStateMachineCommand_Description
//					, ProtocolStateMachine.class
//					, null));
			entries.add(paletteStack);

			//Region
			entries.add(PapyrusPlugin.creationToolFactory.getCombinedTemplateCreationToolEntry(
					PapyrusMessages.AddRegionCommand_Label
					, PapyrusMessages.AddRegionCommand_Description
					, Region.class
					, null));

			paletteStack = new PaletteStack("", "", null);
			//Initial
			paletteStack.add(PapyrusPlugin.creationToolFactory.getCombinedTemplateCreationToolEntry(
					PapyrusMessages.AddPseudostate_initialCommand_Label
					, PapyrusMessages.AddPseudostate_initialCommand_Description
					, Initial.class
					, null));
			//FinalState
			paletteStack.add(PapyrusPlugin.creationToolFactory.getCombinedTemplateCreationToolEntry(
					PapyrusMessages.AddFinalStateCommand_Label
					, PapyrusMessages.AddFinalStateCommand_Description
					, FinalState.class
					, null));
			entries.add(paletteStack);

			paletteStack = new PaletteStack("", "", null);
			//State
			paletteStack.add(PapyrusPlugin.creationToolFactory.getCombinedTemplateCreationToolEntry(
					PapyrusMessages.AddStateCommand_Label
					, PapyrusMessages.AddStateCommand_Description
					, State.class
					, null));
			entries.add(paletteStack);
			
			paletteStack = new PaletteStack("", "", null);
			//Choice
			paletteStack.add(PapyrusPlugin.creationToolFactory.getCombinedTemplateCreationToolEntry(
					PapyrusMessages.AddPseudostate_choiceCommand_Label
					, PapyrusMessages.AddPseudostate_choiceCommand_Description
					, Choice.class
					, null));
			//Junction
			paletteStack.add(PapyrusPlugin.creationToolFactory.getCombinedTemplateCreationToolEntry(
					PapyrusMessages.AddPseudostate_junctionCommand_Label
					, PapyrusMessages.AddPseudostate_junctionCommand_Description
					, Junction.class
					, null));
			entries.add(paletteStack);

			paletteStack = new PaletteStack("", "", null);
			//DeepHistory
			paletteStack.add(PapyrusPlugin.creationToolFactory.getCombinedTemplateCreationToolEntry(
					PapyrusMessages.AddPseudostate_deepHistoryCommand_Label
					, PapyrusMessages.AddPseudostate_deepHistoryCommand_Description
					, DeepHistory.class
					, null));
			//ShallowHistory
			paletteStack.add(PapyrusPlugin.creationToolFactory.getCombinedTemplateCreationToolEntry(
					PapyrusMessages.AddPseudostate_shallowHistoryCommand_Label
					, PapyrusMessages.AddPseudostate_shallowHistoryCommand_Description
					, ShallowHistory.class
					, null));
			entries.add(paletteStack);
			
			paletteStack = new PaletteStack("", "", null);
			//EntryPoint
			paletteStack.add(PapyrusPlugin.creationToolFactory.getCombinedTemplateCreationToolEntry(
					PapyrusMessages.AddPseudostate_entryPointCommand_Label
					, PapyrusMessages.AddPseudostate_entryPointCommand_Description
					, EntryPoint.class
					, null));
			//ExitPoint
			paletteStack.add(PapyrusPlugin.creationToolFactory.getCombinedTemplateCreationToolEntry(
					PapyrusMessages.AddPseudostate_exitPointCommand_Label
					, PapyrusMessages.AddPseudostate_exitPointCommand_Description
					, ExitPoint.class
					, null));
			//Terminate
			paletteStack.add(PapyrusPlugin.creationToolFactory.getCombinedTemplateCreationToolEntry(
					PapyrusMessages.AddPseudostate_terminateCommand_Label
					, PapyrusMessages.AddPseudostate_terminateCommand_Description
					, Terminate.class
					, null));
			entries.add(paletteStack);
			
			//ConnectionPointReference
			entries.add(PapyrusPlugin.creationToolFactory.getCombinedTemplateCreationToolEntry(
					PapyrusMessages.AddConnectionPointReferenceCommand_Label
					, PapyrusMessages.AddConnectionPointReferenceCommand_Description
					, ConnectionPointReference.class
					, null));
			
			paletteStack = new PaletteStack("", "", null);
			//Fork
			paletteStack.add(PapyrusPlugin.creationToolFactory.getCombinedTemplateCreationToolEntry(
					PapyrusMessages.AddPseudostate_forkCommand_Label
					, PapyrusMessages.AddPseudostate_forkCommand_Description
					, Fork.class
					, null));
			//Join
			paletteStack.add(PapyrusPlugin.creationToolFactory.getCombinedTemplateCreationToolEntry(
					PapyrusMessages.AddPseudostate_joinCommand_Label
					, PapyrusMessages.AddPseudostate_joinCommand_Description
					, Join.class
					, null));
			entries.add(paletteStack);

			//Comment
			entries.add(PapyrusPlugin.creationToolFactory.getCombinedTemplateCreationToolEntry(
					PapyrusMessages.AddCommentCommand_Label
					, PapyrusMessages.AddCommentCommand_Description
					, Comment.class
					, null));

			//Constraint
			entries.add(PapyrusPlugin.creationToolFactory.getCombinedTemplateCreationToolEntry(
					PapyrusMessages.AddConstraintCommand_Label
					, PapyrusMessages.AddConstraintCommand_Description
					, Constraint.class
					, null));
		}
		catch (Exception e) {
			PapyrusMessageDialog.display(e.getMessage(), e);
		}

		componentsDrawer.addAll(entries);

		return componentsDrawer;
	}

	/**
	 * Create the "Tools" group.
	 * 
	 * @param palette the palette
	 * 
	 * @return the palette container
	 */
	private static PaletteContainer createToolsGroup(PaletteRoot palette){
		Debug.debug(null,"Call StateMachinePaletteFactory.createToolsGroup()", channel);
		
		//PaletteDrawer componentsDrawer = new PaletteDrawer("RelationShips");
		PaletteGroup toolGroup = new PaletteGroup("RelationShips");

		//Add a selection tool to the group
		ToolEntry tool = new PanningSelectionToolEntry();
		toolGroup.add(tool);
		palette.setDefaultEntry(tool);

		//Add a marquee tool to the group
		toolGroup.add(new MarqueeToolEntry());

		//Add a (unnamed) separator to the group
		toolGroup.add(new PaletteSeparator());

		List entries = new ArrayList();
		try{
			PaletteStack paletteStack = new PaletteStack("", "", null);
			//ProtocolConformance
//			paletteStack.add(PapyrusPlugin.creationToolFactory.getConnectionCreationToolEntry(
//					PapyrusMessages.AddProtocolConformanceCommand_Label
//					, PapyrusMessages.AddProtocolConformanceCommand_Description
//					, ProtocolConformance.class
//					, null));
//			//ProtocolTransition
//			paletteStack.add(PapyrusPlugin.creationToolFactory.getConnectionCreationToolEntry(
//					PapyrusMessages.AddProtocolTransitionCommand_Label
//					, PapyrusMessages.AddProtocolTransitionCommand_Description
//					, ProtocolTransition.class
//					, null));
//			entries.add(paletteStack);

//			paletteStack = new PaletteStack("", "", null);
		
//			//Transition_external
//			paletteStack.add(PapyrusPlugin.creationToolFactory.getConnectionCreationToolEntry(
//					PapyrusMessages.AddTransition_externalCommand_Label
//					, PapyrusMessages.AddTransition_externalCommand_Description
//					, Transition.class
//					, TransitionKind.EXTERNAL_LITERAL));
//			//Transition_internal
//			paletteStack.add(PapyrusPlugin.creationToolFactory.getConnectionCreationToolEntry(
//					PapyrusMessages.AddTransition_internalCommand_Label
//					, PapyrusMessages.AddTransition_internalCommand_Description
//					, Transition.class
//					, TransitionKind.INTERNAL_LITERAL));
//			//Transition_local
//			paletteStack.add(PapyrusPlugin.creationToolFactory.getConnectionCreationToolEntry(
//					PapyrusMessages.AddTransition_localCommand_Label
//					, PapyrusMessages.AddTransition_localCommand_Description
//					, Transition.class
//					, TransitionKind.LOCAL_LITERAL));
//			entries.add(paletteStack);

//			paletteStack = new PaletteStack("", "", null);
			//CommentLink
			//Transition
			paletteStack.add(PapyrusPlugin.creationToolFactory.getConnectionCreationToolEntry(
					PapyrusMessages.AddTransitionCommand_Label
					, PapyrusMessages.AddTransitionCommand_Description
					, Transition.class
					, null));
			entries.add(paletteStack);

			///////////////////////////////////////////////////////////////////
			// Begin of tool for Comment and constraint links
			///////////////////////////////////////////////////////////////////
			
			// Add GraphicalLink
			entries.add(PapyrusPlugin.creationToolFactory.getConnectionCreationToolEntry(
					PapyrusMessages.AddGraphicalLinkCommand_Label,
					PapyrusMessages.AddGraphicalLinkCommand_Description,
					GraphicalLink.class,
					null));	
		}
		catch (Exception e) {
			PapyrusMessageDialog.display(e.getMessage(), e);
		}
		toolGroup.addAll(entries);
		return toolGroup;	
	}
}